<?php
namespace zake\foundation\point;

use zake\foundation\able\ProtocolAble;
use zake\foundation\able\reactor\ConnectAble;
use zake\foundation\able\stream\ReadBufferAble;
use zake\helper\Console;


/**
 * Class Frame
 * @package Foundation\protocol
 *
 * 通信协议
 *
 * 基于固定包头的通信协议
 * 包头长度：4个字节，32位
 *
 */
class Segment implements ProtocolAble
{


    /**
     * @var Segment | null
     */
    private static $singleton = null;


    /**
     * 固定包头
     *
     * 4个字节 32位
     *
     */
    const HEAD_OFFSET = 4;


    /**
     * 包最大长度
     */
    const PACKAGE_MAX_LENGTH = 65535;


    /**
     * 构造器
     *
     * @author liu.bin 2020-04-03 23:16
     */
    public static function singleton()
    {
        if(is_null(static::$singleton)){
            static::$singleton = new static();
        }
        return static::$singleton;
    }




    /**
     * 计算frameLength
     *
     * @param string $buffer
     * @param ReadBufferAble $connect
     *
     * @return int|false
     *          int - 数据包长度（0-没有获取到长度）
     *          false - 数据包错误，需要关闭当前链接
     * @author liu.bin 2020-05-19 16:29
     */
    public function framePoint($buffer,ReadBufferAble $connect)
    {

        if(empty($buffer)){
            Console::warnning("[segment] - 1");
            return false;
        }


        // 不满足:必须大于 frame 的固定头
        $bufferLength = strlen($buffer);
        if($bufferLength <= self::HEAD_OFFSET){
            Console::warnning("[segment] - 2");
            return 0;
        }


        $unpack = unpack('Nlength', $buffer);
        $length = $unpack['length']??0;
        if(empty($length)){

            Console::warnning("[segment] - 3");

            return false;
        }

        // 数据包满足当前frame长度
        if($bufferLength >= $length){

            Console::warnning("[segment] - 4");
            return (int)$length;
        }


        // 返回数据包长度
        Console::warnning("[segment] - 5");
        return 0;

    }



    /**
     * 解包 格式化输出数据包的内容
     *
     * @param string $buffer
     * @return string
     */
    public function decode($buffer,ConnectAble $connect=null)
    {
        return substr($buffer,self::HEAD_OFFSET);
    }


    /**
     * 打包
     *
     * N：32为整形,4个字节
     * 整包长度需要加上 4个字节
     *
     *
     * @param string $buffer
     * @return string
     */
    public function encode($buffer,ConnectAble $connect=null)
    {
        $packageLength  = strlen($buffer) + self::HEAD_OFFSET;
        $buffer         = pack('N',$packageLength) . $buffer;
        return $buffer;
    }

}
